package ssh

import (
	"rc/config"
	"rc/remote/param"
	"rc/utils"
	"time"
)

// SSHRunner execute command by ssh
type SSHRemote struct {
	sc *SSHClient
	sf *SFTPClient
}

func NewSSHRemote(user, password, keyPath, host string, port int) *SSHRemote {
	sc := NewSSHClient(user, password, keyPath, host, port)
	sf := NewSFTPClient(sc, config.GetConfig().BufferSize)

	return &SSHRemote{
		sc: sc,
		sf: sf,
	}
}

// Login login to remote server with shell
func (sr *SSHRemote) Login() error {
	return sr.sc.Shell()
}

func (sr *SSHRemote) Exec(execUser, cmd string) *param.ExecOutput {
	cmd = utils.CompositCommand(execUser, cmd)
	var output = &param.ExecOutput{Status: param.Fail}
	// get exec timeout from config
	var cfg = config.GetConfig()

	output.ExecStart = time.Now()
	status, stdout, stderr, err := sr.sc.ExecNointeractiveCmd(cmd, time.Duration(cfg.ExecTimeout)*time.Second)
	output.ExecEnd = time.Now()

	output.Status = status
	output.Err = err
	output.StdOutput = string(stdout.Bytes())
	output.StdError = string(stderr.Bytes())

	return output
}

func (sr *SSHRemote) ExecInteractive(execUser, cmd string) error {
	cmd = utils.CompositCommand(execUser, cmd)

	return sr.sc.ExecInteractiveCmd(cmd)
}

func (sr *SSHRemote) Get(localPath, remotePath string) *param.RcpOutput {
	rcpStart := time.Now()
	err := sr.sf.Get(localPath, remotePath, nil)

	return &param.RcpOutput{
		RcpStart: rcpStart,
		RcpEnd:   time.Now(),
		Err:      err,
	}
}

func (sr *SSHRemote) Put(localPath, remotePath string) *param.RcpOutput {
	rcpStart := time.Now()
	err := sr.sf.Put(localPath, remotePath, nil)

	return &param.RcpOutput{
		RcpStart: rcpStart,
		RcpEnd:   time.Now(),
		Err:      err,
	}
}
